﻿using System;
using System.Collections.Generic;
using System.Linq;

public class OrderDetails
{
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    public int Quantity { get; set; }

    public decimal Total => Price * Quantity;

    public override bool Equals(object obj)
    {
        return obj is OrderDetails details &&
               ProductName == details.ProductName;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(ProductName);
    }

    public override string ToString()
    {
        return $"{ProductName} 单价：{Price:C} 数量：{Quantity} 小计：{Total:C}";
    }
}

public class Order
{
    public string OrderId { get; set; }
    public string Customer { get; set; }
    public List<OrderDetails> Details { get; } = new List<OrderDetails>();
    public decimal TotalAmount => Details.Sum(d => d.Total);

    public override bool Equals(object obj)
    {
        return obj is Order order &&
               OrderId == order.OrderId;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(OrderId);
    }

    public void AddDetail(OrderDetails detail)
    {
        if (Details.Contains(detail))
            throw new ArgumentException("商品已存在于订单明细中");
        Details.Add(detail);
    }

    public override string ToString()
    {
        return $"订单号：{OrderId}\n客户：{Customer}\n总金额：{TotalAmount:C}\n明细：\n  {string.Join("\n  ", Details)}";
    }
}

public class OrderService
{
    private List<Order> orders = new List<Order>();

    public void AddOrder(Order order)
    {
        if (orders.Contains(order))
            throw new InvalidOperationException("订单已存在");
        orders.Add(order);
    }

    public void RemoveOrder(string orderId)
    {
        var order = orders.FirstOrDefault(o => o.OrderId == orderId);
        if (order == null)
            throw new InvalidOperationException("订单不存在");
        orders.Remove(order);
    }

    public void UpdateOrder(Order newOrder)
    {
        var index = orders.FindIndex(o => o.OrderId == newOrder.OrderId);
        if (index == -1)
            throw new InvalidOperationException("订单不存在");
        orders[index] = newOrder;
    }

    public IEnumerable<Order> QueryOrders(Func<Order, bool> predicate)
        => orders.Where(predicate).OrderBy(o => o.TotalAmount);

    public IEnumerable<Order> GetOrdersByProduct(string productName)
        => orders.Where(o => o.Details.Any(d => d.ProductName == productName))
               .OrderBy(o => o.TotalAmount);

    public IEnumerable<Order> GetOrdersByCustomer(string customer)
        => orders.Where(o => o.Customer == customer)
               .OrderBy(o => o.TotalAmount);

    public void SortOrders(Comparison<Order> comparison = null)
    {
        orders.Sort(comparison ?? ((a, b) => a.OrderId.CompareTo(b.OrderId)));
    }

    public void DisplayAll() => orders.ForEach(Console.WriteLine);
}

class Program
{
    static OrderService service = new OrderService();

    static void Main()
    {
        while (true)
        {
            Console.WriteLine("\n1.添加订单 2.删除订单 3.修改订单 4.查询 5.显示所有 6.退出");
            switch (Console.ReadLine())
            {
                case "1": AddOrder(); break;
                case "2": DeleteOrder(); break;
                case "3": UpdateOrder(); break;
                case "4": SearchOrders(); break;
                case "5": service.DisplayAll(); break;
                case "6": return;
            }
        }
    }

    static void AddOrder()
    {
        var order = new Order
        {
            OrderId = GetInput("订单号"),
            Customer = GetInput("客户")
        };

        while (true)
        {
            var detail = new OrderDetails
            {
                ProductName = GetInput("商品名称（留空结束）"),
                Price = decimal.TryParse(GetInput("单价"), out decimal p) ? p : 0,
                Quantity = int.TryParse(GetInput("数量"), out int q) ? q : 0
            };

            if (string.IsNullOrEmpty(detail.ProductName)) break;

            try { order.AddDetail(detail); }
            catch (ArgumentException ex) { Console.WriteLine(ex.Message); }
        }

        try { service.AddOrder(order); }
        catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); }
    }

    static void DeleteOrder()
    {
        try { service.RemoveOrder(GetInput("订单号")); }
        catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); }
    }

    static void UpdateOrder()
    {
        var oldId = GetInput("要修改的订单号");
        var oldOrder = service.QueryOrders(o => o.OrderId == oldId).FirstOrDefault();
        if (oldOrder == null) { Console.WriteLine("订单不存在"); return; }

        var newOrder = new Order
        {
            OrderId = oldId,
            Customer = GetInput($"新客户（当前：{oldOrder.Customer}）") ?? oldOrder.Customer
        };

        Console.WriteLine("输入新明细（留空保留原明细）：");
        if (!string.IsNullOrEmpty(GetInput("是否清除原明细？(y/n)")))
            oldOrder.Details.ForEach(d => newOrder.AddDetail(d));

        while (true)
        {
            var detail = new OrderDetails
            {
                ProductName = GetInput("商品名称（留空结束）"),
                Price = decimal.TryParse(GetInput("单价"), out decimal p) ? p : 0,
                Quantity = int.TryParse(GetInput("数量"), out int q) ? q : 0
            };

            if (string.IsNullOrEmpty(detail.ProductName)) break;

            try { newOrder.AddDetail(detail); }
            catch (ArgumentException ex) { Console.WriteLine(ex.Message); }
        }

        try { service.UpdateOrder(newOrder); }
        catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); }
    }

    static void SearchOrders()
    {
        Console.WriteLine("1.按订单号 2.按商品 3.按客户 4.按金额范围");
        var result = Console.ReadLine() switch
        {
            "1" => service.QueryOrders(o => o.OrderId == GetInput("订单号")),
            "2" => service.GetOrdersByProduct(GetInput("商品名称")),
            "3" => service.GetOrdersByCustomer(GetInput("客户名称")),
            "4" => service.QueryOrders(o =>
                o.TotalAmount >= decimal.Parse(GetInput("最小金额")) &&
                o.TotalAmount <= decimal.Parse(GetInput("最大金额"))),
            _ => Enumerable.Empty<Order>()
        };

        result.ToList().ForEach(o => Console.WriteLine(o + "\n"));
    }

    static string GetInput(string prompt)
    {
        Console.Write($"{prompt}：");
        return Console.ReadLine();
    }
}